package com.world.system.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.world.common.exception.GlobalException;
import com.world.common.utils.SecurityUtils;
import com.world.system.domain.SysOssFile;
import com.world.system.domain.dto.OssFileDto;
import com.world.system.domain.vo.OssFileResp;
import com.world.system.domain.vo.FileUploadReq;
import com.world.system.factory.OssFactory;
import com.world.system.mapper.SysOssFileMapper;
import com.world.system.service.ISysOssFileService;
import com.world.system.service.OssStrategy;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ContentDisposition;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;

import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;

/**
 * @Author: LiJunXi
 * @Description:
 * @Date: 2024-11-12  18:02
 */
@Service
public class SysOssFileServiceImpl implements ISysOssFileService {

    @Autowired
    private SysOssFileMapper fileMapper;

    @Autowired
    private OssFactory ossFactory;

    @Value("${url.backend}")
    private String backendUrl;


    @Override
    public OssFileResp upload(FileUploadReq req) {
        checkUploadParams(req);
        // 检查是否已经存在
        SysOssFile findFile = checkIfUpload(req);
        if (Objects.nonNull(findFile)) {
            // 已经存在，无需上传OSS
            SysOssFile saveFile = BeanUtil.copyProperties(findFile, SysOssFile.class);
            saveFile.setUserId(SecurityUtils.getUserId());
            saveFile.setCreateTime(LocalDateTime.now());
            fileMapper.save(saveFile);

            OssFileResp ossFileResp = BeanUtil.copyProperties(saveFile, OssFileResp.class);
            ossFileResp.setDownloadUrl(getFileDownloadUrl(saveFile.getId()));
            return ossFileResp;
        }
        OssStrategy ossStrategy = ossFactory.getOssStrategy();
        // 保存到数据库
        SysOssFile sysOssFile = BeanUtil.copyProperties(req, SysOssFile.class);
        sysOssFile.setOssType(ossFactory.getOssType());
        sysOssFile.setTotalSize(req.getFile().getSize());
        sysOssFile.setUserId(SecurityUtils.getUserId());
        sysOssFile.setFilename(req.getFile().getOriginalFilename());
        sysOssFile.setCreateTime(LocalDateTime.now());

        // 保存到OSS
        OssFileDto fileDto = BeanUtil.copyProperties(sysOssFile, OssFileDto.class);
        try {
            fileDto.setFileData(req.getFile().getBytes());
            fileDto.setMultipartFile(req.getFile());
            ossStrategy.saveFile(fileDto);
        } catch (Exception e){
            throw new GlobalException("保存文件出错");
        }

        sysOssFile.setFilePath(fileDto.getFilePath());
        fileMapper.save(sysOssFile);

        OssFileResp ossFileResp = BeanUtil.copyProperties(sysOssFile, OssFileResp.class);
        ossFileResp.setDownloadUrl(getFileDownloadUrl(sysOssFile.getId()));
        return ossFileResp;
    }

    private SysOssFile checkIfUpload(FileUploadReq req) {
        List<SysOssFile> files = fileMapper.selectByMd5(req.getFileMd5());
        if (CollectionUtil.isEmpty(files)) {
            return null;
        }
        return files.get(0);
    }

    private String getFileDownloadUrl(Long fileId) {
        return backendUrl + "/system/oss/download/" + fileId;
    }

    private void checkUploadParams(FileUploadReq req) {
        if(Objects.isNull(req) || Objects.isNull(req.getFile()) || StrUtil.isEmpty(req.getFileMd5())){
            throw new GlobalException("必要参数不能为空");
        }
    }

    @Override
    public ResponseEntity<byte[]> download(Long fileId) {
        OssStrategy ossStrategy = ossFactory.getOssStrategy();
        SysOssFile SysOssFile = fileMapper.getById(fileId);
        byte[] fileData = ossStrategy.getFile(SysOssFile);
        HttpHeaders headers = new HttpHeaders();
        ContentDisposition contentDisposition = ContentDisposition.attachment()
                .filename(SysOssFile.getFilename(), StandardCharsets.UTF_8)
                .build();
        headers.setContentDisposition(contentDisposition);
        return ResponseEntity.ok()
                .headers(headers)
                .contentLength(fileData.length)
                .contentType(MediaType.APPLICATION_OCTET_STREAM)
                .body(fileData);
    }

    @Override
    public SysOssFile getById(Long fileId) {
        return fileMapper.getById(fileId);
    }
}
